﻿using System;
using IList = System.Collections.IList;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Criterion;
using BotonJXC.Entity;

namespace BotonJXC.DAO
{
    public abstract class NHibernateDao<T, PK>
        where T : BaseEntity
    {
        string _identifierPropertyName;
        public NHibernateDao()
        { }

        protected ICriteria CreateCriteria(params ICriterion[] criterions)
        {
            ICriteria criteria = HBHelper.Session.CreateCriteria<T>();
            if (criterions != null)
            {
                foreach (ICriterion c in criterions)
                {
                    criteria.Add(c);
                }
            }
            return criteria;
        }

        protected IQuery CreateQuery(string queryString, params object[] values)
        {
            IQuery query = HBHelper.Session.CreateQuery(queryString);
            if (values != null)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    query.SetParameter(i, values[i]);
                }
            }
            return query;
        }
        public IList<T> Find(ICriterion[] criterions, Order order, int start, int length)
        {
            ICriteria criteria = CreateCriteria(criterions);
            if (order != null)
                criteria.AddOrder(order);
            if (start > -1)
                criteria.SetFirstResult(start);
            if (length > -1)
                criteria.SetMaxResults(length);
            IList<T> list = criteria.List<T>();
            return list;
        }
        public PageModel<T> FindByPage(ICriterion[] criterions, Order order, int start, int length)
        {
            PageModel<T> pageModel = new PageModel<T>();
            pageModel.Results = Find(criterions, order, start, length);
            pageModel.PageSize = length;
            pageModel.TotalCount = GetTotalCount(criterions);
            pageModel.PageNo = (start + length) / length;
            return pageModel;
        }

        public int GetTotalCount(ICriterion[] criterions)
        {
            //获取总记录数
            ICriteria criteria = CreateCriteria(criterions);
            criteria.SetProjection(Projections.RowCount());
            return criteria.UniqueResult<int>();
        }
        protected int ExecuteUpdate(string hql, params object[] parameters)
        {
            IQuery query = CreateQuery(hql, parameters);
            int row = query.ExecuteUpdate();
            return row;
        }
        public string IdentifierPropertyName
        {
            get
            {
                if (string.IsNullOrEmpty(_identifierPropertyName))
                {
                    NHibernate.Metadata.IClassMetadata meta = HBHelper.SessionFactory.GetClassMetadata(typeof(T));
                    _identifierPropertyName = meta.IdentifierPropertyName;
                }
                return _identifierPropertyName;
            }
        }

        public string EntityName
        {
            get
            {
                Type t = typeof(T);
                return t.Name;
            }
        }

        public void Save(T entity)
        {
            HBHelper.Session.Save(entity);
        }
        public virtual void Delete(T entity)
        {
            HBHelper.Session.Delete(entity);
        }
        public virtual void Delete(PK id)
        {
            Delete(Get(id));
        }
        public virtual void Update(T entity)
        {
            HBHelper.Session.Update(entity);
        }
        public T Get(PK pk)
        {
            T t = HBHelper.Session.Get<T>(pk);
            return t;
        }
        public IList<T> FindByIds(params PK[] ids)
        {
            return Find(Restrictions.In(IdentifierPropertyName, ids));
        }
        public IList<T> Find(params ICriterion[] criterions)
        {
            IList<T> list = CreateCriteria(criterions).List<T>();
            return list;
        }
        protected IList<T> Find(string hql, params object[] parameters)
        {
            IQuery query = CreateQuery(hql, parameters);
            return query.List<T>();
        }
        public IList<T> FindBy(string propertyName, object value)
        {
            ICriterion criterion = Restrictions.Eq(propertyName, value);
            return Find(criterion);
        }
        public T FindUniqueBy(string propertyName, object value)
        {
            ICriterion criterion = Restrictions.Eq(propertyName, value);
            T t = (T)CreateCriteria(criterion).UniqueResult();
            return t;
        }
        public T FindUnique(params ICriterion[] criterions)
        {
            T t = (T)CreateCriteria(criterions).UniqueResult();
            return t;
        }
        public IList FindByNamedQuery(string queryName, params object[] parameters)
        {
            IQuery query = HBHelper.Session.GetNamedQuery(queryName);
            if (parameters != null)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    query.SetParameter(i, parameters[i]);
                }
            }
            IList list = query.List();
            return list;
        }
    }
}